package com.one.tank;

//游戏逻辑-->较难理解
public class GameLogic {
    //唯一实例
    private static GameLogic instance;
    //游戏面板
    private GamePanel gamePanel;

    /**
     * 构造函数
     *
     * @param gamePanel 游戏面板
     */
    public GameLogic(GamePanel gamePanel) {
        this.gamePanel = gamePanel;
    }

    /**
     * 得到唯一实例
     */
    public static GameLogic getInstance() {
        return instance;
    }

    /**
     * 设置唯一实例
     *
     * @param gameLogic 游戏逻辑
     */
    public static void setInstance(GameLogic gameLogic) {
        instance = gameLogic;
    }

    /**
     * 判断矩形1是否碰撞到矩形2
     *
     * @param x1 矩形1 左上角X坐标
     * @param y1 矩形1 左上角Y坐标
     * @param w1 矩形1 宽度
     * @param h1 矩形1 高度
     * @param x2 矩形2 左上角X坐标
     * @param y2 矩形2 左上角Y坐标
     * @param w2 矩形2 宽度
     * @param h2 矩形2 高度
     */
    public boolean rectCollideRect(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
        // 判断原理（1、矩形1的四个顶点是否落在矩形2里；2、矩形2的四个顶点是否落在矩形1里。若高度或宽阔相等时特殊判断）
        // 这个碰撞判断比较严，必须进入才算碰撞，挨着不算
        // 判断矩形1的四个顶点是否落在矩形2里
        if ((x1 > x2 && x1 < x2 + w2 && y1 > y2 && y1 < y2 + h2)
                || (x1 + w1 > x2 && x1 + w1 < x2 + w2 && y1 > y2 && y1 < y2 + h2)
                || (x1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 + h1 < y2 + h2)
                || (x1 + w1 > x2 && x1 + w1 < x2 + w2 && y1 + h1 > y2 && y1 + h1 < y2 + h2)) {
            return true;
        }
        // 判断矩形2的四个顶点是否落在矩形1里
        if ((x2 > x1 && x2 < x1 + w1 && y2 > y1 && y2 < y1 + h1)
                || (x2 + w2 > x1 && x2 + w2 < x1 + w1 && y2 > y1 && y2 < y1 + h1)
                || (x2 > x1 && x2 < x1 + w1 && y2 + h2 > y1 && y2 + h2 < y1 + h1)
                || (x2 + w2 > x1 && x2 + w2 < x1 + w1 && y2 + h2 > y1 && y2 + h2 < y1 + h1)) {
            return true;
        }
        // 特殊情况处理
        // 若2个矩形的宽度相等时
        if (w1 == w2) {
            if (x1 == x2 && x1 + w1 == x2 + w2 && ((y1 > y2 && y1 < y2 + h2) || (y1 + h1 > y2 && y1 + h1 < y2 + h2))) {
                return true;
            }
        }
        // 若2个矩形的高度相等时
        if (h1 == h2) {
            if (y1 == y2 && y1 + h1 == y2 + h2 && ((x1 > x2 && x1 < x2 + w2) || (x1 + w1 > x2 && x1 + w1 < x2 + w2))) {
                return true;
            }
        }
        // 2个矩形完全重合
        if (x1 == x2 && y1 == y2 && w1 == w2 && h1 == h2) {
            return true;
        }
        return false;
    }

    /**
     * 判断坦克移动时的下一个位置是否碰撞到任何对象
     */
    public boolean tankMoveCollide(Tank tank) {
        int newX = tank.getX();
        int newY = tank.getY();
        // 得到移动后的新坐标
        switch (tank.getDirection()) {
            case Tank.UP:
                newY = tank.getY() - tank.getSpeed();
                break;
            case Tank.RIGHT:
                newX = tank.getX() + tank.getSpeed();
                break;
            case Tank.DOWN:
                newY = tank.getY() + tank.getSpeed();
                break;
            case Tank.LEFT:
                newX = tank.getX() - tank.getSpeed();
                break;
        }
        // 判断是否碰撞到边界
        switch (tank.getDirection()) {
            case Tank.UP:
                if (newY < 0) {
                    return true;
                }
                break;
            case Tank.RIGHT:
                if (newX + Tank.TANK_WIDTH > GamePanel.GAME_WIDTH) {
                    return true;
                }
                break;
            case Tank.DOWN:
                if (newY + Tank.TANK_HEIGHT > GamePanel.GAME_HEIGHT) {
                    return true;
                }
                break;
            case Tank.LEFT:
                if (newX < 0) {
                    return true;
                }
                break;
        }
        // 判断是否碰撞到敌方坦克
        for (int i = 0; i < gamePanel.getEnemyPool().size(); i++) {
            EnemyTank enemy = gamePanel.getEnemyPool().get(i);
            if (enemy.getState() == Tank.TANK_GO && tank != enemy) {
                if (rectCollideRect(newX, newY, Tank.TANK_WIDTH, Tank.TANK_HEIGHT, enemy.getX(), enemy.getY(), Tank.TANK_WIDTH, Tank.TANK_HEIGHT)) {
                    return true;
                }
            }
        }
        // 判断是否碰撞到我方坦克
        if (tank.getType() == Tank.TANK_TYPE_ENEMY) {
            if (rectCollideRect(newX, newY, Tank.TANK_WIDTH, Tank.TANK_HEIGHT, gamePanel.getOurTank().getX(), gamePanel.getOurTank().getY(), Tank.TANK_WIDTH, Tank.TANK_HEIGHT)) {
                return true;
            }
        }
        // 判断是否碰撞到块
        for (Block block : gamePanel.getBlockList()) {
            if (rectCollideRect(newX, newY, Tank.TANK_WIDTH, Tank.TANK_HEIGHT, block.getX(), block.getY(), Block.BLOCK_WIDTH, Block.BLOCK_HEIGHT)) {
                return true;
            }
        }
        // 判断是否碰撞大本营
        if (gamePanel.getCamp().getState() == Camp.CAMP_STATE_RUNNING) {
            if (rectCollideRect(newX, newY, Tank.TANK_WIDTH, Tank.TANK_HEIGHT, gamePanel.getCamp().getX(), gamePanel.getCamp().getY(), gamePanel.getCamp().getWidth(), gamePanel.getCamp().getHeight())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断坦克是否碰撞到坦克
     *
     * @param tank1 坦克1
     * @param tank2 坦克2
     */
    public boolean tankCollideTank(Tank tank1, Tank tank2) {
        return rectCollideRect(tank1.getX(), tank1.getY(), Tank.TANK_WIDTH, Tank.TANK_HEIGHT, tank2.getX(), tank2.getY(), Tank.TANK_WIDTH, Tank.TANK_HEIGHT);
    }

    /**
     * 判断子弹是否碰撞到坦克
     */
    public boolean bulletCollideTank(Bullet bullet, Tank tank) {
        return rectCollideRect(bullet.getX(), bullet.getY(), bullet.getWidth(), bullet.getHeight(), tank.getX(), tank.getY(), Tank.TANK_WIDTH, Tank.TANK_HEIGHT);
    }

    /**
     * 判断子弹是否碰撞到块
     */
    public boolean bulletCollideBlock(Bullet bullet, Block block) {
        return rectCollideRect(bullet.getX(), bullet.getY(), bullet.getWidth(), bullet.getHeight(), block.getX(), block.getY(), Block.BLOCK_WIDTH, Block.BLOCK_HEIGHT);
    }

    /**
     * 判断子弹是否碰撞到大本营
     */
    public boolean bulletCollideCamp(Bullet bullet, Camp camp) {
        return rectCollideRect(bullet.getX(), bullet.getY(), bullet.getWidth(), bullet.getHeight(), camp.getX(), camp.getY(), camp.getWidth(), camp.getHeight());
    }

    /**
     * 得到某范围内的随机整数
     *
     * @param min 最小值
     * @param max 最大值
     */
    public static int getRandomInt(int min, int max) {
        return (int) (Math.random() * (max - min + 1) + min);
    }
}

